package com.archermind.style.service;

import com.archermind.style.bean.*;
import com.archermind.style.pojo.ElementEnum;
import com.feng.fengDUtil.BaseService;
import com.archermind.style.util.Result;
import com.archermind.style.util.Search;
import com.archermind.style.util.SessionUtil;
import com.feng.fengDUtil.Page;
import org.apache.commons.lang3.StringUtils;
import org.apache.tomcat.util.collections.CaseInsensitiveKeyMap;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.util.*;

@Service
@Transactional
public class InstanceService  extends BaseService {

    private static final Logger log = LoggerFactory.getLogger(InstanceService.class);

    @Autowired
    private DictService dictService;

    @Autowired
    private IconService iconService;
    @Autowired
    private StyleTypeService styleTypeService;

    @Autowired
    private RuleService ruleService;

    @Autowired
    private SceneService sceneService;
    @Autowired
    private OperationService opService;

    public Result processXml(MultipartFile file, Instance instance) throws Exception {
        InputStream is = file.getInputStream();
        SAXReader saxReader = new SAXReader();
        Document doc = saxReader.read(is);
        is.close();
        Element root = doc.getRootElement();
        System.out.println( "获取了根元素:"+root.getName()  );

        instance.setCreator(SessionUtil.getCurUserId());
        instance.setCreateTime(new Date());
        saveOrUpdate(instance);

        styleTypeService.styleMap.set(new CaseInsensitiveKeyMap<>());
        dictService.colorMap.set(new CaseInsensitiveKeyMap<>());
        dictService.iconMap.set(new CaseInsensitiveKeyMap<>());
        ruleService.textStyleMap.set(new HashMap<>());
        List conflicts  =  styleTypeService.processXMLDom(root);
        if(conflicts.size()>0){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return new Result(2,"重复样式id共"+conflicts.size()+" 条：",conflicts);
        }
        dictService.processXMLDom(root. element("CommonStyleDefine"),instance.getId());
        ruleService.processXMLDom(root,instance.getId());
        styleTypeService.saveInstanceStyle(instance.getId());

        String comment = "导入了新样式："+ getInstanceName(instance.getId());
        opService.saveLog(comment,instance.getId());
        return null;
    }

    public boolean isUnique(Long id,String name){
        ArrayList params = new ArrayList();
        String sql = "select 1 from instance where name = ? ";
        params.add(name);
        if(id!=null){
            sql+=" and id != ? ";
            params.add(id);
        }
        Long one = sql(sql+" limit 1").one(Long.class, params.toArray());
        return one == null;
    }

    @Transactional
    public Page query(Page page,Search search) {
        ArrayList params = new ArrayList();
        String sql = "select u.*," +
                "(select s.name From user s where s.id = u.creator limit 1) as creatorName," +
                "(select s.name From user s where s.id = u.modifier limit 1) as modifierName" +
                " from instance u where 1=1 ";

        User user = SessionUtil.getCurUser();
        if(!user.getId().equals(1)){
            Set instanceIds =  SessionUtil.getInstanceIds(user);
            if(instanceIds.isEmpty()){
                return page;
            }else{
                sql+=" and id in ("+genePlaceHolders(instanceIds.size())+")";
                params.addAll(instanceIds);
            }
        }
        if(StringUtils.isNotEmpty(search.getInIds())){
            String[] idArray = search.getInIds().split(",");
            sql+=" and id in ("+genePlaceHolders(idArray.length)+")";
            params.addAll(Arrays.asList(idArray));
        }
        if(StringUtils.isNotEmpty(search.getNotInIds())){
            String[] idArray = search.getNotInIds().split(",");
            sql+=" and id not in ("+genePlaceHolders(idArray.length)+")";
            params.addAll(Arrays.asList(idArray));
        }
        if(StringUtils.isNotEmpty(search.getName())){
            sql+=" and name like ?";
            params.add(processLike(search.getName()));
        }
        if(search.getSceneId()!=null){
            sql+=" and sceneId = ?";
            params.add(search.getSceneId());
        }

        sql+="  order by id desc";
        findPageList(Map.class,sql,page,params.toArray());
        return page;
    }

    public Instance getInstance(Integer instanceId) {
       return  sql("select u.*,(select s.code from scene s where s.id = u.sceneId) sceneCode from instance u where u.id = ?").one(Instance.class,instanceId);
    }

    public String getInstanceName(Integer instanceId){
        String sql ="select concat(s.text,'>',i.name) from scene s join instance i on s.id = i.sceneId where i.id = ?";
        return sql(sql).one(String.class,instanceId);
    }

    public void delInstances(String ids) {
        String[] idArray = ids.split(",");
        String instanceNames = sql("select group_concat(name) from instance where id in ("+genePlaceHolders(idArray.length)+")").one(String.class,idArray);
        opService.saveLog("删除了样式："+instanceNames);

        for(ElementEnum element:ElementEnum.values()){
            if(element.getType()!=null && element.getType()>0){
                sql("delete from rule_"+element.name()+" where instanceId in ("+genePlaceHolders(idArray.length) +")").update(idArray);
            }
        }
        sql("delete from dict_color where instanceId in ("+genePlaceHolders(idArray.length)+")").update(idArray);
        sql("delete from dict_font where instanceId in ("+genePlaceHolders(idArray.length)+")").update(idArray);
        sql("delete from dict_font_size where instanceId in ("+genePlaceHolders(idArray.length)+")").update(idArray);
        sql("delete from dict_dash_line where instanceId in ("+genePlaceHolders(idArray.length)+")").update(idArray);
        sql("delete from instance_icon where instanceId in ("+genePlaceHolders(idArray.length)+")").update(idArray);
        sql("delete from instance_style where instanceId in ("+genePlaceHolders(idArray.length)+")").update(idArray);
        deleteByIds(Instance.class,ids);
    }

    public void copyInstance(Instance instance) throws Exception{
        Integer oldInstanceId = instance.getId();


        List<RulePoint> points = sql("select * from rule_point where instanceId = ?").list(RulePoint.class,oldInstanceId);
        List<RuleLine> lines = sql("select * from rule_line where instanceId = ?").list(RuleLine.class,oldInstanceId);
        List<RulePolygon> polygons = sql("select * from rule_polygon where instanceId = ?").list(RulePolygon.class,oldInstanceId);
        List<RuleBuilding> buildings = sql("select * from rule_building where instanceId = ?").list(RuleBuilding.class,oldInstanceId);
        List<RuleArrow> arrows = sql("select * from rule_arrow where instanceId = ?").list(RuleArrow.class,oldInstanceId);
        List<RuleRoadSign> ruleRoadSigns = sql("select * from rule_roadSign where instanceId = ?").list(RuleRoadSign.class,oldInstanceId);

        List<DictColor> colors = sql("select * from dict_color where instanceId = ?").list(DictColor.class,oldInstanceId);
        List<DictFont> fonts = sql("select * from dict_font where instanceId = ?").list(DictFont.class,oldInstanceId);
        List<DictFontSize> fontSizes = sql("select * from dict_font_size where instanceId = ?").list(DictFontSize.class,oldInstanceId);
        List<DictDashLine> dashLines = dictService.getDictDashLines(oldInstanceId);

        transKeyToObj(points, lines, polygons, buildings, arrows, ruleRoadSigns, colors, fonts, fontSizes, dashLines);

        instance.setId(null);
        instance.setModifier(null);
        instance.setModifyTime(null);
        instance.setCreator(SessionUtil.getCurUserId());
        instance.setCreateTime(new Date());
        insert(instance);

        Integer instanceId = instance.getId();
        for(DictColor dict:colors){
            dict.setId(null);
            dict.setInstanceId(instanceId);
            insert(dict);
        }
        for(DictFont dict:fonts){
            dict.setId(null);
            dict.setInstanceId(instanceId);
            insert(dict);
        }
        for(DictFontSize dict:fontSizes){
            dict.setId(null);
            dict.setInstanceId(instanceId);
            insert(dict);
        }
        for(DictDashLine dict:dashLines){
            dict.setId(null);
            dict.setInstanceId(instanceId);
            insert(dict);
        }

        //更新dictId
        for(RulePoint item:points){
            item.setFontName(dictService.getDictFontId(item.getDictFontName()));
            item.setFontSize(dictService.getDictFontSizeId(item.getDictFontSize()));
            item.setFontColor(dictService.getDictColorId(item.getDictFontColor()));
            item.setHalocolor(dictService.getDictColorId(item.getDictHalocolor()));
            item.setInstanceId(instanceId);
            item.setId(null);
            insert(item);
        }
        for(RuleLine item:lines){
            item.setDashLineName(dictService.getDictDashLineId(item.getDictDashLineName()));
            item.setStroke(dictService.getDictColorId(item.getDictStroke()));
            item.setStrokeSide(dictService.getDictColorId(item.getDictStrokeSide()));
            item.setFontName(dictService.getDictFontId(item.getDictFontName()));
            item.setFontSize(dictService.getDictFontSizeId(item.getDictFontSize()));
            item.setFontColor(dictService.getDictColorId(item.getDictFontColor()));
            item.setHalocolor(dictService.getDictColorId(item.getDictHalocolor()));
            item.setInstanceId(instanceId);
            item.setId(null);
            insert(item);
        }
        for(RulePolygon item:polygons){
            item.setBorderColor(dictService.getDictColorId(item.getDictBorderColor()));
            item.setFill(dictService.getDictColorId(item.getDictFill()));
            item.setInstanceId(instanceId);
            item.setId(null);
            insert(item);
        }
        for(RuleBuilding item:buildings){
            item.setRoofColor(dictService.getDictColorId(item.getDictRoofColor()));
            item.setRootColor(dictService.getDictColorId(item.getDictRootColor()));
            item.setWallColor(dictService.getDictColorId(item.getDictWallColor()));
            item.setWindowColor(dictService.getDictColorId(item.getDictWindowColor()));
            item.setRoofLineColor(dictService.getDictColorId(item.getDictRoofLineColor()));
            item.setWallLineColor(dictService.getDictColorId(item.getDictWallLineColor()));
            item.setRoofLineColor2d(dictService.getDictColorId(item.getDictRoofLineColor2d()));
            item.setRoofColor2d(dictService.getDictColorId(item.getDictRoofColor2d()));
            item.setInstanceId(instanceId);
            item.setId(null);
            insert(item);
        }
        for(RuleArrow item:arrows){
            item.setColor(dictService.getDictColorId(item.getDictColor()));
            item.setInstanceId(instanceId);
            item.setId(null);
            insert(item);
        }
        for(RuleRoadSign item:ruleRoadSigns){
            item.setFontName(dictService.getDictFontId(item.getDictFontName()));
            item.setFontSize(dictService.getDictFontSizeId(item.getDictFontSize()));
            item.setFontColor(dictService.getDictColorId(item.getDictFontColor()));
            item.setHalocolor(dictService.getDictColorId(item.getDictHalocolor()));
            item.setInstanceId(instanceId);
            item.setId(null);
            insert(item);
        }

        /*List<IconSprite> iconSprites = sql("select * from instance_icon where instanceId = ?").list(IconSprite.class,oldInstanceId);
        for(IconSprite item:iconSprites){
            item.setInstanceId(instanceId);
            item.setId(null);
            insert(item);
        }*/
        sql("insert into instance_icon(fileName,instanceId,aliasName,styleID) select fileName,?,aliasName,styleID from instance_icon where instanceId = ?").update(new Integer[]{instanceId,oldInstanceId});
        sql("insert into instance_style select ? as instanceId,styleTypeId,textTypeId,tagForModify,textTag from instance_style where instanceId = ?").update(new Integer[]{instanceId,oldInstanceId});

        refreshInstanceIcon(instance.getId());

        String comment ="复制了样式。从"+getInstanceName(oldInstanceId)+"至"+sceneService.getSceneName(instance.getSceneId())+">"+instance.getName();
        opService.saveLog(comment,instanceId);
    }

    void transKeyToObj(List<RulePoint> points, List<RuleLine> lines, List<RulePolygon> polygons, List<RuleBuilding> buildings, List<RuleArrow> arrows, List<RuleRoadSign> ruleRoadSigns, List<DictColor> colors, List<DictFont> fonts, List<DictFontSize> fontSizes, List<DictDashLine> dashLines) {
        for(RulePoint item:points){
            item.setDictFontName(dictService.getDictFont(item.getFontName(),fonts));
            item.setDictFontSize(dictService.getDictFontSize(item.getFontSize(),fontSizes));
            item.setDictFontColor(dictService.getDictColor(item.getFontColor(),colors));
            item.setDictHalocolor(dictService.getDictColor(item.getHalocolor(),colors));
        }

        for(RuleLine item:lines){
            item.setDictDashLineName(dictService.getDictDashLine(item.getDashLineName(),dashLines));
            item.setDictStroke(dictService.getDictColor(item.getStroke(),colors));
            item.setDictStrokeSide(dictService.getDictColor(item.getStrokeSide(),colors));
            item.setDictFontName(dictService.getDictFont(item.getFontName(),fonts));
            item.setDictFontSize(dictService.getDictFontSize(item.getFontSize(),fontSizes));
            item.setDictFontColor(dictService.getDictColor(item.getFontColor(),colors));
            item.setDictHalocolor(dictService.getDictColor(item.getHalocolor(),colors));
        }

        for(RulePolygon item:polygons){
            item.setDictBorderColor(dictService.getDictColor(item.getBorderColor(),colors));
            item.setDictFill(dictService.getDictColor(item.getFill(),colors));
        }

        for(RuleBuilding item:buildings){
            item.setDictRoofColor(dictService.getDictColor(item.getRoofColor(),colors));
            item.setDictRootColor(dictService.getDictColor(item.getRootColor(),colors));
            item.setDictWallColor(dictService.getDictColor(item.getWallColor(),colors));
            item.setDictWindowColor(dictService.getDictColor(item.getWindowColor(),colors));
            item.setDictRoofLineColor(dictService.getDictColor(item.getRoofLineColor(),colors));
            item.setDictWallLineColor(dictService.getDictColor(item.getWallLineColor(),colors));
            item.setDictRoofLineColor2d(dictService.getDictColor(item.getRoofLineColor2d(),colors));
            item.setDictRoofColor2d(dictService.getDictColor(item.getRoofColor2d(),colors));
        }

        for(RuleArrow item:arrows){
            item.setDictColor(dictService.getDictColor(item.getColor(),colors));
        }

        for(RuleRoadSign item:ruleRoadSigns){
            item.setDictFontName(dictService.getDictFont(item.getFontName(),fonts));
            item.setDictFontSize(dictService.getDictFontSize(item.getFontSize(),fontSizes));
            item.setDictFontColor(dictService.getDictColor(item.getFontColor(),colors));
            item.setDictHalocolor(dictService.getDictColor(item.getHalocolor(),colors));
        }
    }


    /**
     * 刷新样式的引用图标集合
     * @param instanceId
     */
    public void refreshInstanceIcon(Integer instanceId){
        String sql = "delete u from instance_icon u where u.instanceId = ? and  " +
                "not exists (select 1 from rule_point p where p.instanceId = u.instanceId and p.iconName = u.fileName) and " +
                "not exists (select 1 from rule_line p where p.instanceId = u.instanceId and (p.strokeTexture = u.fileName or p.sideTexture = u.fileName or p.sideWallTexture = u.fileName)) and " +
                "not exists (select 1 from rule_polygon p where p.instanceId = u.instanceId and (p.regionTexture = u.fileName or p.borderTexture = u.fileName  )) and " +
                "not exists (select 1 from rule_building p where p.instanceId = u.instanceId and (p.roofTexture = u.fileName or p.wallTexture = u.fileName) ) and " +
                "not exists (select 1 from rule_arrow p where p.instanceId = u.instanceId and p.texture = u.fileName) and " +
                "not exists (select 1 from rule_roadSign p where p.instanceId = u.instanceId and p.iconname = u.fileName) ";
       int cnt = sql(sql).update(new Integer[]{instanceId});
        System.out.println("删除了"+cnt+"个图标引用！");

        String insertSql = "insert into instance_icon(fileName,instanceId) \n" +
                "select iconName fileName,instanceId from rule_point where instanceId = ? and iconName is not null and  not exists (select 1 from instance_icon p where p.instanceId = rule_point.instanceId and p.fileName = rule_point.iconName)\n" +
                "union \n" +
                "select strokeTexture fileName,instanceId from rule_line where instanceId = ? and strokeTexture is not null and  not exists (select 1 from instance_icon p where p.instanceId = rule_line.instanceId and p.fileName = rule_line.strokeTexture)\n" +
                "union \n" +
                "select sideWallTexture fileName,instanceId from rule_line  where instanceId = ? and sideWallTexture is not null and  not exists (select 1 from instance_icon p where p.instanceId = rule_line.instanceId and p.fileName = rule_line.sideWallTexture)\n" +
                "union \n" +
                "select sideTexture fileName,instanceId from rule_line  where instanceId = ? and sideTexture is not null and  not exists (select 1 from instance_icon p where p.instanceId = rule_line.instanceId and p.fileName = rule_line.sideTexture)\n" +
                "union \n" +
                "select regionTexture fileName,instanceId from rule_polygon  where instanceId = ? and regionTexture is not null and  not exists (select 1 from instance_icon p where p.instanceId = rule_polygon.instanceId and p.fileName = rule_polygon.regionTexture)\n" +
                "union \n" +
                "select borderTexture fileName,instanceId from rule_polygon  where instanceId = ? and borderTexture is not null and  not exists (select 1 from instance_icon p where p.instanceId = rule_polygon.instanceId and p.fileName = rule_polygon.borderTexture)\n" +
                "union \n" +
                "select roofTexture fileName,instanceId from rule_building  where instanceId = ? and roofTexture is not null and  not exists (select 1 from instance_icon p where p.instanceId = rule_building.instanceId and p.fileName = rule_building.roofTexture)\n" +
                "union \n" +
                "select wallTexture fileName,instanceId from rule_building  where instanceId = ? and wallTexture is not null and  not exists (select 1 from instance_icon p where p.instanceId = rule_building.instanceId and p.fileName = rule_building.wallTexture)\n" +
                "union \n" +
                "select texture fileName,instanceId from rule_arrow  where instanceId = ? and texture is not null and  not exists (select 1 from instance_icon p where p.instanceId = rule_arrow.instanceId and p.fileName = rule_arrow.texture)\n" +
                "union \n" +
                "select iconname fileName,instanceId from rule_roadSign  where instanceId = ? and iconname is not null and  not exists (select 1 from instance_icon p where p.instanceId = rule_roadSign.instanceId and p.fileName = rule_roadSign.iconname)\n ";
        sql(insertSql).update(new Integer[]{instanceId,instanceId,instanceId,instanceId,instanceId,instanceId,instanceId,instanceId,instanceId,instanceId});
    }


    public void test() {
        IconType type = new IconType();
        type.setText("丰建立");
        insert(type);

        AttachmentFolder folder = iconService.selectById(AttachmentFolder.class,100);
        iconService.test();
        folder = iconService.selectById(AttachmentFolder.class,100);
        sql("select 1 from m").one(Long.class);
    }
}
